import arrayMethods from './array.js'
import Dep from './dep.js'
function observe(data){
    
   
   //不是对象类型不需要观测
   if( (typeof data !=='object')) return 
   
   //已经观测过的数据不需要
   if(data.__ob__) return
   

   return new Observer(data)
}

class Observer{
    constructor(data){
       this.dep=new Dep()  //这个dep专门给数组用的

       //给观测的对象添加观测属性方法，但是不能被枚举
        Object.defineProperty(data,'__ob__',{
            value:this,
            enumerable:false
        }) 

       if(Array.isArray(data)){
          data.__proto__=arrayMethods
          this.observeArray(data)
       }else{
        this.walk(data)
       }
       
    }
    observeArray(data){
        //对数组中的每一项进行观测，看是否有对象要变成响应式
        data.forEach(item=>{
            observe(item)
        })
    }
    walk(data){
       
        //遍历data的每一项，劫持重新定义
        Object.keys(data).forEach(key=>{
            defineReactive(data,key,data[key])
        })

    }
}

function defineReactive(data,key,value){
    let dep=new Dep()
   let childObj= observe(value)   //深度递归观测每一项

    Object.defineProperty(data,key,{
        get(){
            if(Dep.target){
                //在html里有取值，就会第一次收集依赖
                dep.depend()    //收集依赖
                if(childObj){
                    childObj.dep.depend()   //收集数组中的依赖
                    if(Array.isArray(value)){
                        denpendArray(value)  //收集数组中套数组的依赖
                    }
                    
                }
            }
            return value
        },
        set(newValue){
            if(value!==newValue){
                value=newValue
                observe(value)   //新设置的值也要进行观测
                dep.notify()   //触发依赖更新
            }
        }
    })
}

function denpendArray(value){
    //对数组深度收集依赖
    for(let item of value){
        item.__ob__&&item.__ob__.dep.depend()
        if(Array.isArray(item)){
            denpendArray(item)
        }
    }
}

export default observe